#include "muduo/net/TcpServer.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/TcpConnection.h"
#include <functional>
#include <iostream>
#include <string>
#include <unordered_map>
using namespace std;
using namespace placeholders;

// muduo-主从reactor
class TranslateServer
{
public:
    TranslateServer(int port)
        : _svr(&_loop, muduo::net::InetAddress("0.0.0.0", port),
               "TranslateServer", muduo::net::TcpServer::kReusePort)
    {
        dict_init(); // 初始化字典表

        // 设置回调函数
        _svr.setConnectionCallback(std::bind(&TranslateServer::myconnect, this, _1));
        _svr.setMessageCallback(std::bind(&TranslateServer::mydeal, this, _1, _2, _3));
    }
    void start()
    {
        _svr.start(); // 创建套接字+将套接字设置到_loop(epoll)事件
        _loop.loop(); // 死循环阻塞,等待监听套接字事件到来,然后进行IO处理,回调_svr里设置的的回调函数
    }

private:
    void dict_init()
    {
        _dict["hello"] = "你好";
        _dict["计算机"] = "computer";
        _dict["向左"] = "turn left";
        _dict["向右"] = "turn right";
        _dict["向前"] = "forward";
        _dict["向后"] = "backwards";
    }
    // 连接就绪(listen_socket)就绪的回调函数
    void myconnect(const muduo::net::TcpConnectionPtr &conn)
    {
        if (conn->connected())
        {
            cout << "新连接建立成功" << endl;
        }
        else
        {
            cout << "连接关闭" << endl;
        }
    }
    // 收到请求后的回调处理函数
    void mydeal(const muduo::net::TcpConnectionPtr &conn, muduo::net::Buffer *buf,
                muduo::Timestamp)
    {
        // 1.获取请求数据
        string req = buf->retrieveAllAsString();

        // 2.处理请求数据
        string rsp;
        if (!_dict.count(req))
            rsp = "not find!";
        else
            rsp = _dict[req];

        // 3.结果响应回去
        conn->send(rsp);
    }

private:
    // EventLoop对象必须在TcpServer对象之前，因为TcpServer对象在初始化列表中用到了EventLoop
    muduo::net::EventLoop _loop;         // epoll事件监听+IO操作
    muduo::net::TcpServer _svr;          // 设置回调处理数据请求
    unordered_map<string, string> _dict; // 字典表
};

int main()
{
    TranslateServer svr(8888);
    svr.start();

    return 0;
}
